#ifndef DBUS_MANAGER_HPP
#define DBUS_MANAGER_HPP

#include <systemd/sd-bus.h>
#include <memory>
#include <string>
#include <vector>

#include "LogCollectionPrivate.hpp"

//! 工具类，集成dbus 相关服务
class DbusManager
{

static inline const std::string MATHCH_FMT {
    "type='signal',sender='{}',interface='{}',member='{}'"
};

public:
    DbusManager() = default;

    ~DbusManager() = default;

    //! 内部嵌入类，用于包装需要暴露给dbus的接口函数
    template<typename Cls>
    struct Wrapper {
        using ClassFuncPtr = int (Cls::*)(sd_bus_message*, void*, sd_bus_error*);

        //! 包装器函数
        static int call(sd_bus_message* msg, void* userdata, sd_bus_error* err) {
            auto* pair = static_cast<std::pair<Cls*, ClassFuncPtr>*>(userdata);
            Cls* obj = pair->first;
            ClassFuncPtr func = pair->second;
            return (obj->*func)(msg, userdata, err);
        }
    };

    template<typename Cls, typename Func>
    static sd_bus_slot* registerInterface(const char* aFuncName,
        const char* aInput, const char* aOuput, Cls* aObject, Func aFunc,
        sd_bus* aBus, const char* aServicePath, const char* aServiceInterface)
    {
        using ClassFuncPtr = typename Wrapper<Cls>::ClassFuncPtr;
        //! userdata 存储class和func
        auto data = std::make_unique<std::pair<Cls*, ClassFuncPtr>>(aObject, static_cast<ClassFuncPtr>(aFunc));
        auto dataPtr = data.get();

        //! 存储userdata到pool
        static std::vector<std::unique_ptr<std::pair<Cls*, ClassFuncPtr>>> dataPool;
        dataPool.push_back(std::move(data));

        //! 创建vtable
        auto vtable = std::unique_ptr<sd_bus_vtable[]>( new sd_bus_vtable[3] {
            SD_BUS_VTABLE_START(0),
            SD_BUS_METHOD(aFuncName, aInput, aOuput, &Wrapper<Cls>::call, 0),
            SD_BUS_VTABLE_END
        } );
        sd_bus_vtable* vtablePtr = vtable.get();

        //! 存储vtable到pool
        static std::vector<std::unique_ptr<sd_bus_vtable[]>> vtablePool;
        vtablePool.push_back(std::move(vtable));

        sd_bus_slot* slot { nullptr };
        auto ret = sd_bus_add_object_vtable(
            aBus, &slot, aServicePath, aServiceInterface, vtablePtr, dataPtr
        );
        
        return slot;
    }

    static void unregisterInterface(sd_bus_slot* aSlot);

    static bool emitSignal(const char* aSignal,
        sd_bus* aBus, const char* aServicePath, const char* aServiceInterface);

    template<typename Cls, typename Func>
    static bool matchSignal(const char* aSignal, Cls* aObject, Func aCallback,
        sd_bus* aBus, const char* aServicePath, const char* aServiceInterface)
    {
        using ClassFuncPtr = typename Wrapper<Cls>::ClassFuncPtr;
        //! userdata 存储class和func
        auto data = std::make_unique<std::pair<Cls*, ClassFuncPtr>>(
            aObject, static_cast<ClassFuncPtr>(aCallback));
        auto dataPtr = data.get();    

        //! 存储userdata到pool
        static std::vector<std::unique_ptr<std::pair<Cls*, ClassFuncPtr>>> dataPool;
        dataPool.push_back(std::move(data));

        auto ret = sd_bus_add_match(
            aBus, nullptr, 
            LogCollector::format(MATHCH_FMT, aServicePath, aServiceInterface, aSignal).c_str(),
            &Wrapper<Cls>::call,
            dataPtr
        );

        return ret >= 0;

    };

};


#endif